﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using ObviousCode.Stately.Compiler.Parser;
using ObviousCode.Stately.Compiler.Templating;
using ObviousCode.Stately;
using Token = StatelyCompiler.Token;
using Lexer = StatelyCompiler.Lexer;

namespace TestHarness
{
    public partial class TestForm : Form
    {
        public event EventHandler<EventArgs<Exception>> ParserExceptionOccured;

        public TestForm()
        {
            InitializeComponent();

            _tabs.SelectedIndex = 2;
        }

        private void _lex_Click(object sender, EventArgs e)
        {
            List<Token> tokens = Lex();

            AddTokensToLexOutput(tokens);
        }

        private void AddTokensToLexOutput(List<Token> tokens)
        {
            if (tokens != null) _tokens.Text = String.Join(Environment.NewLine, tokens.Select(t => t.ToString()).ToArray());
        }

        private List<Token> Lex()
        {
            OpenFileDialog ofd = new OpenFileDialog();

            if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                Lexer lexer = new Lexer();

                List<Token> tokens = new List<Token>();

                StringBuilder builder = new StringBuilder();

                using (FileStream stream = File.Open(ofd.FileName, FileMode.Open))
                {
                    lexer.Lex(stream).ForEach(t =>
                    {
                        tokens.Add(t);
                    });
                }

                return tokens;
            }

            return null;
        }

        private void _parse_Click(object sender, EventArgs e)
        {
            List<Token> tokens = Lex();

            if (tokens == null) return;

            Parser parser = new Parser();

            string exception = string.Empty;

            parser.ExceptionOccured += (s, ex) => { exception = ex.Item.Message; };

            parser.Parse(tokens, (d) => AddParseTextToParseOutput(d));
            
            if (!(string.IsNullOrWhiteSpace(exception)))
            {
                _parsed.Text = "{0}{1}{2}".F(_parsed.Text, Environment.NewLine, exception);
            }
        }

        private string AddParseTextToParseOutput(TransformData d)
        {
            return _parsed.Text = String.Join(Environment.NewLine, d.Transitions.Select(ct => ct.ToString()));
        }

        private void _genCode_Click(object sender, EventArgs e)
        {
            List<Token> tokens = Lex();

            AddTokensToLexOutput(tokens);

            PartialClassTemplate template;
            StubClassTemplate stub;
            DataContextTemplate context;

            if (tokens == null) return;

            Parser parser = new Parser();

            string exception = string.Empty;

            parser.ExceptionOccured += (s, ex) => { exception = ex.Item.Message; };

            parser.Parse(tokens, (d) =>
                {
                    AddParseTextToParseOutput(d);

                    if (!string.IsNullOrWhiteSpace(exception)) { _code.Text = "Parser Error: {0}".F(exception); return;  }

                    d.ClassName = "Parser";
                    d.Namespace = "ObviousCode.Stately.Compiler.Parser";
                    d.DataContextName = "CompilerContext";

                    template = new PartialClassTemplate(d);
                    stub = new StubClassTemplate(d);
                    context = new DataContextTemplate(d);

                    _code.Text = "PARTIAL:\r\n_______________\r\n\r\n{0}\r\n\r\nSTUB:\r\n_______________\r\n\r\n{1}\r\n\r\nCONTEXT:\r\n_______________\r\n\r\n{2}\r\n\r\n".F(template.TransformText(), stub.TransformText(), context.TransformText());
                });
        }
    }
}
